#!/data/Software/mydan/perl/bin/perl -I/data/Software/mydan/JOBX/lib -I/data/Software/mydan/JOBX/private/lib
use strict;
use warnings;

use MIME::Base64;
use Data::Dumper;

use Digest::MD5;
use FindBin qw( $RealBin );
use Time::HiRes qw/time/;
use POSIX;
use Code;
use YAML::XS;
use Logs;

use JSON;
use Logs;
use LWP::UserAgent;
use Encode;
use Util;



$| ++;

=head1 SYNOPSIS

    db => $mysql,
    uuid => uuid,

    logs => 日志对象

=cut

return sub
{
    my %param = @_;

    my ( $db, $uuid, $logs ) = @param{qw( db uuid logs )};

    $logs = Logs->new( 'code.subtask' ) unless $logs;

    $logs->die( "uuid format error" ) unless $uuid =~ /^[a-zA-Z0-9]+$/;

    my ( $stimems, $stime ) = ( time, POSIX::strftime( "%Y-%m-%d %H:%M:%S", localtime ) );

    $db->execute( "update subtask set status='running' where uuid='$uuid' and status='init'" );
    my $x = $db->query( "select task.name,projectid,variable,nodelist,subtask.status  from task,subtask where task.uuid=subtask.parent_uuid and subtask.uuid='$uuid'" );
    $logs->die( "get data error from db" ) unless defined $x && ref $x eq 'ARRAY';
    $logs->die( "subtask uuid null: $uuid" ) unless @$x;
    my ( $name, $projectid, $variable, $nodelist, $status ) = @{$x->[0]};

    return $status if grep{ $status eq $_ }qw( cancel success fail refuse );

    if( $variable )
    {
        $variable  = eval{ YAML::XS::Load decode_base64( $variable ) };
        $logs->die( "task variable decode load error:$@" ) if $@;
    }

    $variable = +{} unless $variable;
    $variable->{ip} = $nodelist;

    my $ua = LWP::UserAgent->new();
    $ua->agent('Mozilla/9 [en] (Centos; Linux)');

    my $bytes = encode_utf8($name); 
    $name = $bytes;

    my %env = eval{ Util::envinfo( qw( appkey appname envname ) ) };
    $logs->die( $@ ) if $@;

    $ua->default_header( map{ $_ => $env{$_} }qw( appname appkey) );
 
    $ua->timeout( 10 );
    $ua->default_header ( 'Cache-control' => 'no-cache', 'Pragma' => 'no-cache' );

    while( 1) 
    {
        my $res = $ua->post( 
            "http://api.job.open-c3.org/task/$projectid/job/byname", 
	        Content => JSON::to_json( +{ jobname => $name, uuid => $uuid,  variable => $variable } ), 
	        'Content-Type' => 'application/json' 
        );

        my $cont = $res->content;
        if( $res->is_success )
        {
            my $data = eval{ JSON::from_json $cont };
            if( $@ )
            {
                $logs->say( "calljob fail: $cont : no json $@" );
            }
            else
            {
                if( $data->{stat} )
                {
                    print "call job ok\n";
                    last;
                }
                else
                {
                    $logs->say( "calljob fail: $cont : stat fail" );
                    print "calljob fail: $cont : stat fail\n";
                    eval{ $db->execute( "update subtask set starttime='$stime',finishtime='$stime',runtime=0,status='fail',confirm='' where uuid='$uuid'" ); };
                    $logs->die( "update subtask status fail:$@" ) if $@;
                    return 'fail'
                }
            }
        }
        else
        {
            $logs->say( "calljob fail: $cont" );
        }

        sleep 5;
    }


    my $d;
    while( 1 )
    {
        sleep 5;

        my $res = $ua->get( "http://api.job.open-c3.org/task/$projectid/$uuid" );
    
        my $cont = $res->content;
        if( $res->is_success )
        {
            my $data = eval{ JSON::from_json $cont };
            if( $@ )
            {
                $logs->say( "get job status fail: $cont : no json $@" );
            }
            else
            {
                if( $data->{stat} )
                {
                    $d = $data->{data};
                    my $s = $data->{data}{status};
                    if ( $s && ( $s eq 'success' || $s eq 'fail' || $s eq 'refuse' ) )
                    {
                        if( my @lose =  grep{ ! ( defined $d->{$_} && $d->{$_} !~ /'/  ) }qw( starttime finishtime runtime status ))
                        {
                            $logs->say( sprintf "get job status fail: lose %s", join ',', @lose );
                        }
                        else
                        {
                            last;
                        }
                    }
                    
                }
                else
                {
                    $logs->say( "get job status fail: $cont : stat fail" )
                }
            }
        }
        else
        {
            $logs->say( "get job status fail: $cont" );
        }
    
    }


    my $confirm = $d->{status} eq 'fail' ? 'WaitConfirm' : '';
    eval{ $db->execute( "update subtask set starttime='$d->{starttime}',finishtime='$d->{finishtime}',runtime='$d->{runtime}',status='$d->{status}',confirm='$confirm' where uuid='$uuid'" ); };
    $logs->die( "update subtask status fail:$@" ) if $@;

    if( $d->{status} eq 'fail' )
    {
        while(1)
        {
            sleep 5;
            my $c = $db->query( "select confirm from subtask where uuid='$uuid'" );
            last if $c && $c->[0][0] ne 'WaitConfirm';
        }
    }
    return $d->{status};
}
